Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Twisted Edwards curves operations #1949

Open
wants to merge 33 commits into
base: main
Choose a base branch
from
Open

Conversation

querolita
Copy link
Member

This PR is the twisted counterpart of the operations found in /src/lib/provable/gadgets/elliptic-curve.ts. It is a necessary step to support EdDSA, which uses the twisted curve Ed25519. Related to o1-labs/o1js-bindings#317.

@querolita querolita marked this pull request as ready for review January 10, 2025 22:36
@querolita querolita requested review from a team as code owners January 10, 2025 22:36
@querolita querolita requested review from 45930 and ymekuria January 10, 2025 22:36
@querolita querolita force-pushed the feature/eddsa/twisted branch from b741643 to 576725d Compare January 15, 2025 18:56
Copy link
Member Author

@querolita querolita left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

left some comments for reviewers

toBigint({ x, y }: Point) {
let x_ = Field3.toBigint(x);
let y_ = Field3.toBigint(y);
return { x: x_, y: y_, infinity: x_ === 0n && y_ === 1n };
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created an equivalent Point type (elliptic-curve also has it) with the difference that the infinity is not always set to false as it is the case in the other gadgets.

let witnesses = exists(12, () => {
let [x1_, x2_, y1_, y2_] = Field3.toBigints(x1, x2, y1, y2);

// TODO: reuse code in twistedAdd to avoid recomputing these
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be a nice feature and much cleaner code, but apparently this wouldn't be a trivial refactor at all. Ideas for the future: inspiration from the interpreter structure in o1vm?

* TODO: could use lookups for picking precomputed multiples, instead of O(2^c) provable switch
* TODO: custom bit representation for the scalar that avoids 0, to get rid of the degenerate addition case
*/
function multiScalarMul(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

basically the difference between this function and the counterpart in elliptic-curve.ts is that the Curve is a CurveTwisted instead of an affine curve. I don't know if making this more generic would be a good idea, maybe we want to have a specific implementation for each curve instead of parameterizing it. Open to suggestions (similar concerns arise in other functions of this interface as well).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the only difference between this function and the elliptic-curve.ts counterpart is that the Curve is a CurveTwisted? I'm curious to hear why you lean towards specific implementations of each curve vs a more generic function.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the curve is an affine curve there are some special cases that need to be treated which do not happen in the twisted case. That's the reason that I removed the zeros cases after receiving @mitschabaude's feedback here, so the type is not the only difference.

However, I also thought that having a more generic approach could be beneficial. But then I chatted a bit with @dannywillems, who believed that because elliptic curve operations are so sensitive, it can be a better idea to have almost duplicate implementations of certain functions, instead of maximizing generics. There's room for debate I suppose.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the explanation. I think it makes sense to keep it separate implementations for each curve.

@mitschabaude
Copy link
Collaborator

Since twisted curve addition is complete, there's a lot of complexity in the scalar multiplication code around handling zeros that could be removed. E.g. you don't need the initial aggregator point, and you can just return the result instead of asserting it to be zero or non-zero

@querolita
Copy link
Member Author

@mitschabaude Oh that makes sense, I will look into it and clean the algorithm for twisted msm.

Copy link
Contributor

@45930 45930 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given how complex the witness and assertion logic is for these curve functions, I'd feel more comfortable with more extensive testing.

e.g. instead of testing each method on a random point, can we test a few different points? Are there any special points that could be the source of an edge case error that we could test specifically? Can we also( or at least) test cases where the witnesses will be invalid and confirm that the assertions trigger?

src/lib/provable/gadgets/twisted-curve.ts Outdated Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this file mistakenly added to git? There is no lib/ directory at the top level.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh this is probably a git error yeah, it should be in /src/lib/provable/test/twisted-curve.unit-test.js instead

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a compiled version of the unit test

src/lib/provable/test/twisted-curve.unit-test.ts Outdated Show resolved Hide resolved
src/lib/provable/test/twisted-curve.unit-test.ts Outdated Show resolved Hide resolved
src/lib/provable/test/twisted-curve.unit-test.ts Outdated Show resolved Hide resolved
src/lib/provable/gadgets/twisted-curve.ts Outdated Show resolved Hide resolved
@querolita querolita force-pushed the feature/eddsa/twisted branch from a0f99dc to 8e77d3a Compare January 28, 2025 12:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants